Nacos与Zuul的动态路由

您所在的位置:网站首页 zuul routes配置 Nacos与Zuul的动态路由

Nacos与Zuul的动态路由

#Nacos与Zuul的动态路由| 来源: 网络整理| 查看: 265

Nacos1.0.0 GA版本终于出来了,其中的配置中心非常适合来配置路由信息,我们希望把所有的路由信息配置到Nacos中,并且一旦有变化能够及时变更

构建一个服务提供者

该项目注释简单的提供一个测试接口,并且把自己注册到Nacos当中,其中Pom文件如下

UTF-8 1.8 org.springframework.boot spring-boot-starter-parent 2.0.3.RELEASE org.springframework.cloud spring-cloud-starter-alibaba-nacos-discovery 0.2.1.RELEASE org.springframework.cloud spring-cloud-dependencies Finchley.RELEASE pom import org.springframework.boot spring-boot-starter-web org.springframework.cloud spring-cloud-starter-alibaba-nacos-discovery

编写一个配置文件 application.properties

server.port=18080 spring.application.name=service-provider spring.cloud.nacos.discovery.server-addr=192.168.5.126:80

编写一个主运行类,打上注解即可

@SpringBootApplication @EnableDiscoveryClient public class ProviderApplication { public static void main(String[] args) { SpringApplication.run(ProviderApplication.class, args); } @RestController class EchoController { @RequestMapping(value = "/echo/{string}", method = RequestMethod.GET) public String echo(@PathVariable String string) { return "receive " + string; } } }

到此为止,服务提供者已经完成。接下来开始正式的Zuul集成

构建Zuul项目 Pom文件 UTF-8 1.8 org.springframework.boot spring-boot-starter-parent 2.0.3.RELEASE org.springframework.boot spring-boot-starter-actuator org.springframework.boot spring-boot-starter-web org.springframework.cloud spring-cloud-starter-netflix-zuul com.alibaba fastjson 1.2.47 org.springframework.cloud spring-cloud-starter-alibaba-nacos-discovery 0.2.1.RELEASE com.alibaba.nacos nacos-client org.springframework.cloud spring-cloud-starter-alibaba-nacos-config 0.2.1.RELEASE com.alibaba.nacos nacos-client com.alibaba.nacos nacos-spring-context 0.2.3-RC1 com.alibaba.nacos nacos-client 1.0.0 org.springframework.cloud spring-cloud-dependencies Finchley.RELEASE pom import spring-milestones Spring Milestones https://repo.spring.io/libs-milestone false org.springframework.boot spring-boot-maven-plugin 编写配置文件

bootstrap.properties

nacos.address=192.168.5.126:80 spring.cloud.nacos.discovery.server-addr=${nacos.address} spring.cloud.nacos.config.server-addr=${nacos.address} spring.application.name: zuul-server server.port: 8888 编写主运行类 @SpringBootApplication @EnableDiscoveryClient @EnableZuulProxy public class Application { public static void main(String[] args) { SpringApplication.run(Application.class, args); } }

EnableZuulProxy注解开启了Zuul网关服务

静态类

我们的配置存在nacos上,就需要data_id和group_id,为了方便,把这两个参数放到静态类的常量中,这里使用接口来

public interface Constant { public static final String NACOS_DATA_ID="zuul-server"; public static final String NACOS_GROUP_ID="zuul_route"; } 配置类-nacos配置服务器 @Configuration public class NacosServerConfig { @Value("${spring.cloud.nacos.config.server-addr:127.0.0.1:8848}") private String serverAddr; @Autowired NewZuulRouteLocator routeLocator; @Autowired ApplicationEventPublisher publisher; @Bean public ConfigService configService(){ Properties properties = new Properties(); properties.put(PropertyKeyConst.SERVER_ADDR, serverAddr); try { ConfigService configService = NacosFactory.createConfigService(properties); configService.addListener(NACOS_DATA_ID, NACOS_GROUP_ID, new Listener() { @Override public Executor getExecutor() { //可以发送监听消息到某个MQ return null; } @Override public void receiveConfigInfo(String configInfo) { System.out.println("Nacos更新了!"); //切忌!!!不需要自己去刷新 RoutesRefreshedEvent routesRefreshedEvent = new RoutesRefreshedEvent(routeLocator); publisher.publishEvent(routesRefreshedEvent); } }); return configService; } catch (NacosException e) { e.printStackTrace(); } return null; } } 配置类-zuul配置 /** * 配置路由和监听器 */ @Configuration public class NewZuulConfig { @Autowired private ZuulProperties zuulProperties; @Autowired private ServerProperties serverProperties; /** * * 功能描述: * * @param: * @return: * @auther: tangshun * @date: 2019/4/17 20:18 */ @Bean public NewZuulRouteLocator routeLocator() { NewZuulRouteLocator routeLocator = new NewZuulRouteLocator( this.serverProperties.getServlet().getServletPrefix(), this.zuulProperties); return routeLocator; } @Bean public ApplicationListener zuulRefreshRoutesListener() { return new ZuulRefreshListener(); } } Zuul刷新监听器 /** * @ClassName ZuulRefreshListener * @Author Tangshun * @Description //TODO * @Date 10:42 2019/4/18 * @Version 1.0.0 **/ public class ZuulRefreshListener implements ApplicationListener { @Autowired private ZuulHandlerMapping zuulHandlerMapping; private HeartbeatMonitor heartbeatMonitor = new HeartbeatMonitor(); @Override public void onApplicationEvent(ApplicationEvent event) { if (event instanceof ContextRefreshedEvent || event instanceof RefreshScopeRefreshedEvent || event instanceof RoutesRefreshedEvent) { //设置为脏,下一次匹配到路径时,如果发现为脏,则会去刷新路由信息 this.zuulHandlerMapping.setDirty(true); }else if (event instanceof HeartbeatEvent) { if (this.heartbeatMonitor.update(((HeartbeatEvent) event).getValue())) { this.zuulHandlerMapping.setDirty(true); } } } } 核心类 public class NewZuulRouteLocator extends SimpleRouteLocator implements RefreshableRouteLocator { @Autowired private ZuulProperties properties; @Autowired private PropertiesAssemble propertiesAssemble; public NewZuulRouteLocator(String servletPath, ZuulProperties properties) { super(servletPath, properties); this.properties = properties; } @Override public void refresh() { doRefresh(); } @Override protected Map locateRoutes() { LinkedHashMap routesMap = new LinkedHashMap(); // 从application.properties中加载路由信息 routesMap.putAll(super.locateRoutes()); // 从Nacos中加载路由信息 routesMap.putAll(propertiesAssemble.getProperties()); // 优化一下配置 LinkedHashMap values = new LinkedHashMap(); for (Map.Entry entry : routesMap.entrySet()) { String path = entry.getKey(); // Prepend with slash if not already present. if (!path.startsWith("/")) { path = "/" + path; } if (StringUtils.hasText(this.properties.getPrefix())) { path = this.properties.getPrefix() + path; if (!path.startsWith("/")) { path = "/" + path; } } values.put(path, entry.getValue()); } return values; } } 实体类 public class ZuulRouteEntity { /** * The ID of the route (the same as its map key by default). */ private String id; /** * The path (pattern) for the route, e.g. /foo/**. */ private String path; /** * The service ID (if any) to map to this route. You can specify a * physical URL or a service, but not both. */ private String serviceId; /** * A full physical URL to map to the route. An alternative is to use a * service ID and service discovery to find the physical address. */ private String url; /** * Flag to determine whether the prefix for this route (the path, minus * pattern patcher) should be stripped before forwarding. */ private boolean stripPrefix = true; /** * Flag to indicate that this route should be retryable (if supported). * Generally retry requires a service ID and ribbon. */ private Boolean retryable; private String apiName; private Boolean enabled; public String getId() { return id; } public void setId(String id) { this.id = id; } public String getPath() { return path; } public void setPath(String path) { this.path = path; } public String getServiceId() { return serviceId; } public void setServiceId(String serviceId) { this.serviceId = serviceId; } public String getUrl() { return url; } public void setUrl(String url) { this.url = url; } public boolean isStripPrefix() { return stripPrefix; } public void setStripPrefix(boolean stripPrefix) { this.stripPrefix = stripPrefix; } public Boolean getRetryable() { return retryable; } public void setRetryable(Boolean retryable) { this.retryable = retryable; } public String getApiName() { return apiName; } public void setApiName(String apiName) { this.apiName = apiName; } public Boolean getEnabled() { return enabled; } public void setEnabled(Boolean enabled) { this.enabled = enabled; } } 组装类 @Component public class PropertiesAssemble{ @Autowired private ConfigService configService; public Map getProperties() { Map routes = new LinkedHashMap(); List results = listenerNacos(NACOS_DATA_ID,NACOS_GROUP_ID); for (ZuulRouteEntity result : results) { if (StringUtils.isBlank(result.getPath()) /*|| org.apache.commons.lang3.StringUtils.isBlank(result.getUrl())*/) { continue; } ZuulRoute zuulRoute = new ZuulRoute(); try { BeanUtils.copyProperties(result, zuulRoute); } catch (Exception e) { } routes.put(zuulRoute.getPath(), zuulRoute); } return routes; } private List listenerNacos (String dataId, String group) { try { String content = configService.getConfig(dataId, group, 5000); System.out.println("从Nacos返回的配置:" + content); return JSONObject.parseArray(content, ZuulRouteEntity.class); } catch (NacosException e) { e.printStackTrace(); } return new ArrayList(); } } nacos配置

在nacos配置中建立一个配置,data_id 和 group_id 分别是 zuul-server 和 zuul_route [图片上传失败...(image-8f511f-1558663873510)]

内容区域为

[ { "enable":true, "id":"baidu", "path":"/baidu/**", "retryable":false, "stripPrefix":true, "url":"http://www.baidu.com" }, { "enable":true, "id":"163", "path":"/163/**", "retryable":false, "stripPrefix":true, "url":"https://www.163.com" }, { "enable":true, "id":"service-provider", "serviceId":"service-provider", "path":"/provider/**", "retryable":false, "stripPrefix":true } ]

测试,可以开始测试,并且修改nacos的配置再测试,可以看到实现了动态路由

可以开启多个Provider,来测试LB的效果。



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3